﻿Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Reflection
Imports System.Workflow.ComponentModel

Namespace System.Workflow.ComponentModel.Design
    Friend Class PropertyDescriptorUtils
        ' Methods
        Friend Shared Function GetBaseType(ByVal [property] As PropertyDescriptor, ByVal owner As Object, ByVal serviceProvider As IServiceProvider) As Type
            Dim propertyType As Type = Nothing
            owner.GetType
            If (Not owner Is Nothing) Then
                Dim provider As IDynamicPropertyTypeProvider = [TryCast](owner,IDynamicPropertyTypeProvider)
                If (Not provider Is Nothing) Then
                    propertyType = provider.GetPropertyType(serviceProvider, [property].Name)
                End If
            End If
            If (propertyType Is Nothing) Then
                propertyType = [property].PropertyType
            End If
            Return propertyType
        End Function

        Friend Shared Function GetComponent(ByVal context As ITypeDescriptorContext) As IComponent
            Dim site As ISite = If((Not context Is Nothing), PropertyDescriptorUtils.GetSite(context, context.Instance), Nothing)
            If (site Is Nothing) Then
                Return Nothing
            End If
            Return site.Component
        End Function

        Friend Shared Function GetSite(ByVal serviceProvider As IServiceProvider, ByVal component As Object) As ISite
            Dim site As ISite = Nothing
            If (Not component Is Nothing) Then
                If (TypeOf component Is IComponent AndAlso (Not DirectCast(component, IComponent).Site Is Nothing)) Then
                    site = DirectCast(component, IComponent).Site
                End If
                If (((site Is Nothing) AndAlso component.GetType.IsArray) AndAlso (([TryCast](component,Object()).Length > 0) AndAlso TypeOf [TryCast](component,Object())(0) Is IComponent)) Then
                    site = DirectCast([TryCast](component,Object())(0), IComponent).Site
                End If
                If ((site Is Nothing) AndAlso (Not serviceProvider Is Nothing)) Then
                    Dim service As IReferenceService = [TryCast](serviceProvider.GetService(GetType(IReferenceService)),IReferenceService)
                    If (Not service Is Nothing) Then
                        Dim component2 As IComponent = service.GetComponent(component)
                        If (Not component2 Is Nothing) Then
                            site = component2.Site
                        End If
                    End If
                End If
            End If
            If (site Is Nothing) Then
                site = [TryCast](serviceProvider,ISite)
            End If
            Return site
        End Function

        Friend Shared Sub SetPropertyValue(ByVal serviceProvider As IServiceProvider, ByVal propertyDescriptor As PropertyDescriptor, ByVal component As Object, ByVal value As Object)
            Dim dispatcher As New ComponentChangeDispatcher(serviceProvider, component, propertyDescriptor)
            Try 
                propertyDescriptor.SetValue(component, value)
            Catch exception As Exception
                If (TypeOf exception Is TargetInvocationException AndAlso (Not exception.InnerException Is Nothing)) Then
                    Throw exception.InnerException
                End If
                Throw exception
            Finally
                dispatcher.Dispose
            End Try
        End Sub

    End Class
End Namespace

